import ply.lex as lex

# 保留字
reserved = {
    # 英文保留字
    'if': 'IF',
    'else': 'ELSE',
    'while': 'WHILE',
    'for': 'FOR',
    'def': 'DEF',
    'return': 'RETURN',
    'var': 'VAR',
    'int': 'INT',
    'float': 'FLOAT',
    'bool': 'BOOL',
    'true': 'TRUE',
    'false': 'FALSE',

    # 中文保留字（使用不同的Token名称）
    '分支': 'IF_CN',
    '否则': 'ELSE_CN',
    '函数': 'DEF_CN',
    '整数': 'INT_CN',
    '浮点数': 'FLOAT_CN',
    '布尔': 'BOOL_CN',
    '真': 'TRUE_CN',
    '假': 'FALSE_CN',
    '衔尾蛇': 'FOR_CN',
    '反复执行': 'WHILE_CN',
    '变量': 'VAR_CN',
    '提交': 'RETURN_CN',
}

# 标记列表
tokens = [
    'ID', 'NUMBER', 'FLOAT_NUMBER',
    'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MODULO',
    'ASSIGN', 'EQUALS', 'NOT_EQUALS', 'LESS', 'LESS_EQUALS', 'GREATER', 'GREATER_EQUALS',
    'AND', 'OR', 'NOT',
    'LPAREN', 'RPAREN', 'LBRACE', 'RBRACE', 'LBRACKET', 'RBRACKET',
    'COMMA', 'SEMICOLON', 'COLON',
    # 确保所有Token名称唯一
    'IF', 'IF_CN', 'ELSE', 'ELSE_CN', 'WHILE', 'FOR', 'FOR_CN', 'WHILE_CN', 'DEF', 'DEF_CN', 'RETURN', 'RETURN_CN', 'VAR', 'VAR_CN', 
    'INT', 'INT_CN', 'FLOAT', 'FLOAT_CN', 'BOOL', 'BOOL_CN', 'TRUE', 'TRUE_CN', 'FALSE', 'FALSE_CN'
]

# 运算符和标点符号的正则表达式规则
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_MODULO = r'%'
t_ASSIGN = r'='
t_EQUALS = r'=='
t_NOT_EQUALS = r'!='
t_LESS = r'<'
t_LESS_EQUALS = r'<='
t_GREATER = r'>'
t_GREATER_EQUALS = r'>='
t_AND = r'&&'
t_OR = r'\|\|'
t_NOT = r'!'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LBRACKET = r'\['
t_RBRACKET = r'\]'
t_COMMA = r',' 
t_SEMICOLON = r';'
t_COLON = r':'

# 忽略空白字符
t_ignore = ' \t\r'

# 处理换行符
def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

# 忽略注释
def t_COMMENT(t):
    r'//.*'
    pass

# 浮点数
def t_FLOAT_NUMBER(t):
    r'\d+\.\d+'
    t.value = float(t.value)
    return t

# 整数
def t_NUMBER(t):
    r'\d+'
    t.value = int(t.value)
    return t

# 标识符（支持Unicode字符）
def t_ID(t):
    r'[\u4e00-\u9fa5a-zA-Z_][\u4e00-\u9fa5a-zA-Z_0-9]*'
    t.type = reserved.get(t.value, 'ID')  # 检查是否为保留字
    return t

# 错误处理
def t_error(t):
    print(f"非法字符 '{t.value[0]}' 在第 {t.lexer.lineno} 行")
    t.lexer.skip(1)

# 构建词法分析器
lexer = lex.lex()

def tokenize(code):
    """对代码进行词法分析，返回标记流"""
    # 重置词法分析器的行号，避免多次调用时行号累积
    lexer.lineno = 1
    lexer.input(code)
    tokens = []
    while True:
        tok = lexer.token()
        if not tok:
            break
        tokens.append(tok)
    return tokens